package com.tptech.nearme.helper;

import javax.ws.rs.core.MediaType;

import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientResponse;
import org.json.JSONArray;
import org.json.JSONObject;

import com.tptech.nearme.helper.GeocodeResponse.ACCURACY;
import com.tptech.nearme.helper.GeocodeResponse.STATUS;
import com.tptech.nearme.model.Location;


public class GeocodeAction {

	
	public static void main(String[] args) throws Exception {
		GeocodeAction geoCode = new GeocodeAction();
		GeocodeResponse repsonse = geoCode.geocodeAddress("1600+Amphitheatre+Parkway,+Mountain+View,+CA","CA");
		System.out.println(repsonse);
		repsonse = geoCode.reverseGeocode(40.714224,-73.961452);
		System.out.println(repsonse);
	}

	public static GeocodeResponse geocode(String address,String countryCode) throws Exception{
		GeocodeAction action = new GeocodeAction();
		GeocodeResponse response = action.geocodeAddress(address,countryCode);
		return response;
	}
	
	public static Location revgeocode(Double lat,Double lon){
		return null;
	}
	
	public GeocodeResponse geocodeAddress(String address,String country) throws Exception{
		ClientRequest request = new ClientRequest("http://maps.googleapis.com/maps/api/geocode/json?address="
				+ address+"&sensor=false&components=country:"+country.toUpperCase());
		request.accept(MediaType.APPLICATION_JSON);
		ClientResponse<String> response =request.get(String.class);
		String jsonStr = response.getEntity();
		return parseGeocodeResponse(jsonStr);
	}
	
	public GeocodeResponse reverseGeocode(Double lat,Double lon) throws Exception{
		ClientRequest request = new ClientRequest("http://maps.googleapis.com/maps/api/geocode/json?latlng="
				+ lat+","+lon
				+"&sensor=false");
		request.accept(MediaType.APPLICATION_JSON);
		ClientResponse<String> response =request.get(String.class);
		String jsonStr = response.getEntity();
		System.out.println(jsonStr);
		return (GeocodeResponse) parseGeocodeResponse(jsonStr);
	}
	
	
	
	public GeocodeResponse parseGeocodeResponse(String jsonStr) throws Exception{
		return parseGeocodeResponse(new JSONObject(jsonStr));
	}
	private GeocodeResponse parseGeocodeResponse(JSONObject object) throws Exception{
		try{
			String value = object.getString("status");
			if(!value.equalsIgnoreCase(STATUS.OK.name())){
				throw new IllegalArgumentException("Invalid status :"+value);
			}
			GeocodeResponse response = new GeocodeResponse();
			response.setStatus(STATUS.valueOf(value.toUpperCase()));
			JSONObject result= object.getJSONArray("results").getJSONObject(0);
			value = result.getString("formatted_address");
			if(value==null || value.isEmpty()){
				throw new IllegalStateException("Unable to get the address:"+value);
			}
			response.setFormattedAddress(value);
			
			JSONArray array = result.getJSONArray("address_components");
			for (int i = 0; i < array.length(); i++) {
				JSONObject temp = array.getJSONObject(i);
				JSONArray arrayType = temp.getJSONArray("types");
				for (int j = 0; j < arrayType.length(); j++) {
					value = arrayType.getString(j);
					String loc=temp.getString("short_name");
					if(value.equalsIgnoreCase("locality")){
						response.setLocality(loc);
					}
					else if (value.equalsIgnoreCase("sublocality")) {
						response.setSublocality(loc);
					}else if (value.equalsIgnoreCase("postal_code")) {
						response.setPostalCode(loc);
					}
					else if(value.equalsIgnoreCase("country")){
						response.setCountryCode(loc);
					}
				}
			}
			
			value = result.getJSONObject("geometry").getJSONObject("location").getString("lat");
			response.setLat(Double.parseDouble(value));
			
			value = result.getJSONObject("geometry").getJSONObject("location").getString("lng");
			response.setLon(Double.parseDouble(value));
			
			value = result.getJSONObject("geometry").getString("location_type");
			response.setAccuracy(ACCURACY.valueOf(value.toUpperCase()));
			
			
			return response;
			}catch(Exception e){
				throw new Exception("Unable to parse geocde/rev response",e);
			}
	}
}
